package com.lumberer.pay2021.wx.jsapi.payment.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.lumberer.pay2021.util.Result;
import com.lumberer.pay2021.util.WxRequest;
import com.lumberer.pay2021.wx.enums.PublicState;
import com.lumberer.pay2021.wx.init.config.MerchantConfig;
import com.lumberer.pay2021.wx.init.config.RequestURL;
import com.lumberer.pay2021.wx.jsapi.payment.entity.PayData;
import com.lumberer.pay2021.wx.jsapi.payment.entity.notify.Notify;
import com.lumberer.pay2021.wx.jsapi.payment.entity.pay.JsApi;
import com.lumberer.pay2021.wx.jsapi.payment.service.JsApiService;
import com.lumberer.pay2021.wx.verify.VerifyNotify;

/**
 * 
 * @author lumberer 2021-09-13 JSAPI调起支付
 */
@RestController
@RequestMapping("/jsapi")
public class JsApiController {
	@Autowired
	private JsApiService jsapiService;
	@RequestMapping("/get")
	public void get(){
		System.err.println("appid="+MerchantConfig.appid);
		System.err.println("mchid="+MerchantConfig.mchid);
	}
	@RequestMapping("/set")
	public void set(){
		System.err.println("11");
		MerchantConfig.init("123456", "", "", "", "", "");
	}
	/**
	 * 回调验证
	 * @param request
	 * @return
	 */
	@RequestMapping("/call")
	public Map<String,String> callBack(@RequestBody Notify notify,HttpServletRequest request){
		Map<String,String> result=new HashMap<>();
		//微信回调的签名
		try {
			boolean flag=VerifyNotify.verifiedSign(request, notify);
			if(flag){
				result.put("code","SUCCESS");
				result.put("message","成功");
				//如果回调走这里那么就要
				return result;
			}else{
				result.put("code","ERROR");
				result.put("message","失败，未找到序列号相关证书");
				return result;
			}
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("InvalidKeyException:"+e.getMessage());
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("NoSuchAlgorithmException:"+e.getMessage());
		} catch (SignatureException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("SignatureException:"+e.getMessage());
		}
		
	}
	/**
	 * 预支付订单
	 * 
	 * @param data
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	@RequestMapping("")
	public Result transactions(@RequestBody JsApi jsapi, HttpServletRequest request){
		try {
					//ReqParams.mapToModel(jsapi, JsApi.class);
			PayData payData = jsapiService.transactions(jsapi);
			if (null == payData) {
				return Result.error(500, "获取不到prepay_id", payData);
			} else {
				// 进行数据签名，返回前端调用数据
				return Result.success(200, "预支付成功", payData);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return Result.error(500, e.getMessage(), null);
		}
	}

	/**
	 * 微信支付订单号查询
	 * 
	 * @param transaction_id
	 * @return
	 */
	@RequestMapping("/searchWxOrder")
	public Result searchWxOrder(String transaction_id, HttpServletRequest request) {
		if (StringUtils.isEmpty(transaction_id)) {
			throw new RuntimeException("订单号不能为空");
		}
		String uri = new StringBuffer(RequestURL.JSAPI_SEARCH_WX_ORDER).append(transaction_id).append("?mchid=")
				.append(MerchantConfig.mchid).toString();
		// API安全密钥证书
		String results = WxRequest.wxHttpGet(uri);
		JSONObject json = JSONObject.parseObject(results);
		if(StringUtils.isEmpty(json.getString("code"))){
			return Result.success(200, "查询成功", json);
			
		}else{
			return Result.error(PublicState.getState(json.getString("code")), json.getString("message"), json);
		}
		
	}

	/**
	 * 商户订单号查询
	 * 
	 * @param out_trade_no
	 * @return
	 */
	@RequestMapping("/searchOrder")
	public Result searchOrder(String out_trade_no) {
		
		if (StringUtils.isEmpty(out_trade_no)) {
			return Result.error(500, "订单号不能为空", null);
		}
		String uri = new StringBuffer(RequestURL.JSAPI_SEARCH_ORDER).append(out_trade_no).append("?mchid=")
				.append(MerchantConfig.mchid).toString();
		String results = WxRequest.wxHttpGet(uri);
		JSONObject json = JSONObject.parseObject(results);
		if(StringUtils.isEmpty(json.getString("code"))){
			return Result.success(200, "查询成功", json);
		}else{
			return Result.error(PublicState.getState(json.getString("code")), json.getString("message"), json);
		}
	}

	/**
	 * 关闭订单
	 */
	@RequestMapping("/closeOrder")
	public Result closeOrder(String out_trade_no) {
		if (StringUtils.isEmpty(out_trade_no)) {
			return Result.success(500, "订单号不能为空", null);
		}
		String uri = new StringBuffer(RequestURL.JSAPI_CLOSE_ORDER).append(out_trade_no).append("/close").toString();
		JsApi data = new JsApi();
		data.setMchid(MerchantConfig.mchid);
		data.setOut_trade_no(out_trade_no);
		ObjectMapper objectMapper = new ObjectMapper();
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectNode rootNode = objectMapper.createObjectNode();
		rootNode.put("mchid",data.getMchid())
		        .put("out_trade_no",data.getOut_trade_no());
		try {
			objectMapper.writeValue(bos, rootNode);
		} catch (JsonGenerationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		JSONObject res = WxRequest.wxHttpPost(uri, bos);
		if(StringUtils.isEmpty(res.getString("code"))){
			return Result.success(200, "关闭成功", res);
		}else{
			return Result.success(PublicState.getState(res.getString("code")), res.getString("message"), res);
		}
	}

	/**
	 * 下载交易账单
	 * 
	 * @param bill_date
	 * @param bill_type
	 * @param tar_type
	 * @param request
	 * @return
	 * @throws IOException 
	 * @throws Exception
	 */
	@RequestMapping("/tradebill")
	public void tradebill(String bill_date, String bill_type, String tar_type,HttpServletRequest req, HttpServletResponse response) throws IOException {
		StringBuffer uriBf = new StringBuffer(RequestURL.JSAPI_TRADEBILL).append("?bill_date=").append(bill_date);
		if (!StringUtils.isEmpty(bill_type)) {
			uriBf.append("&account_type=").append(bill_type);
		}
		if (!StringUtils.isEmpty(tar_type)) {
			uriBf.append("&tar_type=").append(tar_type);

		}
		String uri = uriBf.toString();

		String res = WxRequest.wxHttpGet(uri);
		JSONObject json = JSONObject.parseObject(res);
		String dow_url = json.getString("download_url");
		if (StringUtils.isEmpty(dow_url)) {	
			// return json.getString("message");
			throw new RuntimeException(json.toString());

		}
		String result=WxRequest.wxHttpDownload(dow_url,response);
		String fileName=bill_date.replaceAll("-","")+"交易";
		download(result,fileName,req,response);
		
	}

	/**
	 * 下载资金账单
	 * 
	 * @param bill_date
	 * @param account_type
	 * @param tar_type
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/fundflowbill")
	public void fundflowbill(String bill_date, String account_type, String tar_type,HttpServletRequest req, HttpServletResponse response) throws Exception{
		StringBuffer uriBf = new StringBuffer(RequestURL.JSAPI_TRADEBILL).append("?bill_date=").append(bill_date);
		if (!StringUtils.isEmpty(account_type)) {
			uriBf.append("&account_type=").append(account_type);
		}
		if (!StringUtils.isEmpty(tar_type)) {
			uriBf.append("&tar_type=").append(tar_type);

		}
		String uri = uriBf.toString();
		
		String res = WxRequest.wxHttpGet(uri);
		JSONObject json = JSONObject.parseObject(res);
		String dow_url = json.getString("download_url");
		if (StringUtils.isEmpty(dow_url)) {
			// return json.getString("message");
			throw new RuntimeException(json.toString());
		}
		String result=WxRequest.wxHttpDownload(dow_url,response);
		String fileName=bill_date.replaceAll("-","")+"资金";
		download(result,fileName,req,response);
		
	}
	private static void download(String result,String fileName,HttpServletRequest req, HttpServletResponse response) throws IOException{
		if(null==result){
			throw new RuntimeException("获取账单信息失败~");
		}else{
			if(result.indexOf("code")>-1){
				JSONObject json=JSONObject.parseObject(result);
				throw new RuntimeException(json.getString("message"));
			}
			String[] res=result.split("\n");
			//统计数据列名
			String[] infoTitle=new String[]{};
			//统计数据
			String[]infoDatas=new String[]{};
			//支付列名
			String[] payTitle=new String[]{};
			//支付数据信息
			List<String[]>  payData=new ArrayList<String[]>();
			boolean flag=false;
			for (int i = 0; i < res.length; i++) {
				if(res[i].indexOf("总交易单数")>-1){
					infoTitle=res[i].split(",");
					flag=true;
					continue;
				}else if(flag){
					//数据最后一行
					infoDatas=res[i].split(",");
					 break;
				}
				if(i==0){
					payTitle=res[i].split(",");
					continue;
				}else{
					payData.add(res[i].split(","));
				}
			}
			//将处理好的数据进行处理成xls
			// 创建excel       
			Workbook wb = new HSSFWorkbook(); 
			
	        // 创建一张工作表
			HSSFSheet sheet = (HSSFSheet) wb.createSheet("sheet1");
			int index = 0;
			HSSFRow row = sheet.createRow(index);
			// 创建第一行的列并向单元格写值
	        HSSFCell cell = row.createCell(0);
	        /***********************支付总统计数据开始*************************************/
			for (int i = 0; i < infoTitle.length; i++) {
				cell = row.createCell(i);
				cell.setCellValue(infoTitle[i]);
				sheet.setColumnWidth(i, infoTitle[i].getBytes().length*2*256);
			}
			index++;
			row = sheet.createRow(index);
			for (int i = 0; i < infoDatas.length; i++) {
				cell = row.createCell(i);
				cell.setCellValue(infoDatas[i]);
			}
			index++;
			/**************************支付总统计数据结束**********************************/
			/***********************支付数据开始*************************************/
			row = sheet.createRow(index);
			for (int i = 0; i < payTitle.length; i++) {
				cell = row.createCell(i);
				cell.setCellValue(payTitle[i]);
				sheet.setColumnWidth(i, payTitle[i].getBytes().length*2*256);
			}
			index++;
			for (int i = 0; i < payData.size(); i++) {
				row = sheet.createRow(index);
				String[] payDatas=payData.get(i);
				for (int j = 0; j <payDatas.length; j++) {
					cell = row.createCell(j);
					cell.setCellValue(payDatas[j]);
				}
				index++;
			}
			/***********************支付数据结束*************************************/
	        // 文件名
	         fileName = fileName+"账单.xls";
	     // 解决文件乱码
	        final String userAgent = req.getHeader("user-agent");
	        if (userAgent != null && userAgent.indexOf("Firefox") >= 0) {
	            fileName = new String(fileName.getBytes(), "ISO8859-1");
	        } else {
	            fileName = URLEncoder.encode(fileName, "UTF8");
	        }
	        // 下载文件
	        response.setContentType("application/octet-stream");
	        response.setHeader("Content-disposition", "attachment;filename="+fileName);
	        response.flushBuffer();
	        wb.write(response.getOutputStream());
		}
	}
}